package com.itcast.spring6.ioc.application_context;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.*;

import java.util.Map;

/**
 * 基于注解方式启动与获取Bean容器数据
 * @author zhangtian105
 * @date 2023/4/26
 * @apiNote
 */
@Slf4j
@Configuration // 该注释表名这是一个配置类 后面的@Bean就是类似于xml中的bean注册
public class ApplicationContextTest {
    public static void main(String[] args) {
        // 创建容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext() ;
        applicationContext.register(ApplicationContextTest.class);

        // 启动应用上下文
        applicationContext.refresh();

        // ioc依赖查找
        // 通过名称获取Bean
        User normalUser1 = (User) applicationContext.getBean("normalUser");
        log.info("applicationContext getBeanByName: {}", JSONUtil.toJsonStr(normalUser1));

        // 通过类型获取Bean
        User normalUser2 = applicationContext.getBean(User.class);
        log.info("applicationContext getBeanByType: {}", JSONUtil.toJsonStr(normalUser2));

        // 依赖查找集合Bean
        if (applicationContext instanceof ListableBeanFactory) {
            ListableBeanFactory listableBeanFactory = (ListableBeanFactory) applicationContext ;
            // 通过类型查找
            Map<String, User> userMap = listableBeanFactory.getBeansOfType(User.class);
            log.info("applicationContext getAll User beans: {}", JSONUtil.toJsonStr(userMap));

            // 通过注解查找
            Map<String, User> annoUserMap = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);
            log.info("applicationContext get User Super Annotation beans: {}", JSONUtil.toJsonStr(annoUserMap));
        }

        // Bean延迟查找
        ObjectProvider<User> beanProvider = applicationContext.getBeanProvider(User.class);
        User user1 = beanProvider.getObject();
        User user2 = beanProvider.getIfAvailable(() -> new User("default", 12)) ;
        log.info("applicationContext getBeanProvider user1: {}", JSONUtil.toJsonStr(user1));
        log.info("applicationContext getBeanProvider user2: {}", JSONUtil.toJsonStr(user2));

        // 关闭spring应用上下文
        applicationContext.close();
    }

    @Bean(name = "normalUser")
    @Lazy // 加上默认是true，表示延迟加载
    public User getUser() {
        User user = new User() ;
        user.setName("zhangsan");
        user.setAge(15);

        return user ;
    }

    @Bean("superUser")
    @Primary // 同一类型的类 @Primary 只能有一个
    public SuperUser getSuperUser() {
        SuperUser user = new SuperUser() ;
        user.setName("lisi");
        user.setAge(18);
        user.setAddress("北京朝阳区");

        return user ;
    }
}
